
#include <Liberty3D/Library/ProjectTool.h>
#include <Liberty3D/Library/IAssetDepotListener.h>
#include <Liberty3D/Library/TaskScheduler.h>
#include <Liberty3D/Library/Task.h>
#include <Liberty3D/Library/Mutex/Abstract.h>
#include <Liberty3D/Engine/AssetFileFolder.h>
#include <Liberty3D/Engine/Path.h>

#include <iostream>

using namespace Liberty::Engine;
using namespace Liberty::Library;
using namespace Liberty::ProjectTool;

namespace Liberty { namespace ProjectTool {
    std::shared_ptr<Project> CurrentProject;
} }

class DepotListener : public IAssetDepotListener {
public:
    std::weak_ptr<IAssetDepot> depot;
    int                        changeCount;
    
    DepotListener() : changeCount(0) {
    }
    
    virtual void assetAdded(const std::string& s) {
        std::cout << "Asset \"" << s << "\" was added.\n";
        changeCount++;
    }
    
    virtual void assetRemoved(const std::string& s) {
        std::cout << "Asset \"" << s << "\" was removed.\n";
        changeCount++;
    }
    
    virtual void assetModified(const std::string& s) {
        std::cout << "Asset \"" << s << "\" was modified.\n";
        changeCount++;
    }
    
    virtual void assetMoved(const std::string& oldName, const std::string& newName) {
        std::cout << "Asset \"" << oldName << "\" was moved to \"" << newName << "\".\n";
        changeCount++;
    }

    virtual void assetUuidDuplicated(const std::string& name, const Liberty::Engine::Uuid& oldId, const Liberty::Engine::Uuid& newId) {
        std::cout << "Asset \"" << name << "\" had it's UUID duplicated. Was " << oldId.toString() << " became " << newId.toString() << ".\n";
        changeCount++;
    }

    virtual void assetImporterModified(const Liberty::Engine::Uuid& uuid) {
        std::cout << "Asset \"" << depot.lock()->pathForUuid(uuid) << "\" has it's importer data modified.\n";
    }

    virtual void assetCachedDataModified(const Liberty::Engine::Uuid& uuid) {
        std::cout << "Asset \"" << depot.lock()->pathForUuid(uuid) << "\" has it's cached data modified.\n";
    }

    virtual void assetBuildDataModified(const Liberty::Engine::Uuid& uuid, const std::string& buildTag) {
        std::cout << "Asset \"" << depot.lock()->pathForUuid(uuid) << "\" has it's build data modified for " + buildTag + ".\n";
    }
};

void detectChanges() {
    std::shared_ptr<DepotListener> listener = std::shared_ptr<DepotListener>(new DepotListener());

    CurrentProject->depot()->addListener(listener);
    std::cout << "Detecting project's files for changes...\n";
    CurrentProject->depot()->detectChanges();
        
    if (listener->changeCount == 0) {
        std::cout << "No change was detected.\n";
    }

    std::cout << "\n";
}

void ParseArguments(int argc, const char * argv[]) {
    int index;
    
    std::string projectFolder(".");
    bool        createProject = false;
    bool        error         = false;
    
    for (index = 1; index < argc; index++) {
        const char* arg = argv[index];
        
        if (strcmp(arg, "--project") == 0) {
            projectFolder = argv[++index];
        }
        else if (strcmp(arg, "--create") == 0) {
            createProject = true;
        }
        else {
            std::cerr << "Error: Unknown argument \"" << arg << "\"\n";
            error = true;
        }
    }

    if (error) {
        exit(1);
    }

    Path::unixifyPath(projectFolder);
    CurrentProject = std::shared_ptr<Project>(new Project(projectFolder, createProject));
    detectChanges();
}

int main(int argc, const char * argv[])
{
    try {
        TaskScheduler::consoleInit();
        ParseArguments(argc, argv);
        TaskScheduler::consoleLoop();
    }
    catch (std::exception ex) {
        std::cerr << "Error: " << ex.what();
        return 1;
    }
    
    return 0;
}
